package top.went.service;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import top.went.db.dao.OrderDao;
import top.went.db.dao.OrderDeliverDetail;
import top.went.db.dao.OrderDetailDao;
import top.went.db.dao.OutStorageDao;
import top.went.db.mapper.OrderDetailMapper;
import top.went.db.mapper.OrderMapper;
import top.went.exception.NotFoundException;
import top.went.exception.ServiceException;
import top.went.pojo.*;
import top.went.utils.CodeGenerator;
import top.went.vo.*;


import java.math.BigDecimal;
import java.util.*;


/**
 * 订单
 */
@Service
@Transactional(value = "transactionManager",rollbackFor = ServiceException.class)
public class OrderService {
    @Autowired
    private OrderDao orderDao;
    @Autowired
    private OrderMapper orderMapper;
    @Autowired
    private OrderDetailMapper orderDetailMapper;
    @Autowired
    private ProductService productService;
    @Autowired
    private OrderDetailDao detailDao;
    @Autowired
    private OrderDeliverDetail deliverDetail;
    @Autowired
    private OutStorageDao outStorageDao;
    @Autowired
    private QuoteService quoteService;


    /** 表格排序*/
    private static Map<String,String> map = new HashMap<>();
    static {
        map.put("orderNumber","order_number");
        map.put("orderTotal","order_total");
        map.put("orderTitle","order_title");
    }

    /**
     * 添加订单或者合同
     * @param orderEntity
     * @return
     * @throws ServiceException
     */
    public boolean addOrder(OrderEntity orderEntity) throws ServiceException {
        orderEntity.setLoginDelete(false);
        orderEntity.setOrderOk(0);
        if (orderEntity.getOrderTitle() == null || orderEntity.getOrderTitle().length() <=0)
            orderEntity.setOrderTitle("无主题");
        orderEntity.setOrderNumber(CodeGenerator.orderGenerator(orderEntity.getOrderType()));
        try{
            orderDao.save(orderEntity);
        }catch (Exception e){
            e.printStackTrace();
            throw new ServiceException("添加订单/合同失败");
        }
        return true;
    }

    /**
     * 删除合同或者订单
     * @param id
     * @return
     * @throws NotFoundException
     * @throws ServiceException
     */
    public boolean deleteOrder(Long id) throws NotFoundException, ServiceException {
        OrderEntity orderEntity = load(id);
        if (orderEntity.getOrderOk() != 0 && orderEntity.getOrderOk() !=3)
            throw new ServiceException("合同/订单已锁定");
        //需要修改
        if (orderEntity.getTbDeliverDetailsByOrderId().size() > 0)
            throw new ServiceException("该订单/合同已经产生发货记录");
        orderEntity.setLoginDelete(true);
        try {
            orderDao.save(orderEntity);
        }catch (Exception e){
            e.printStackTrace();
            throw new ServiceException("删除订单/合同失败");
        }
        return true;
    }

    /**
     * 加载订单
     * @param id
     * @return
     * @throws NotFoundException
     */
    public OrderEntity load(Long id) throws NotFoundException {
        OrderEntity orderEntity = orderDao.findOne(false,id.intValue());
        if (orderEntity == null)
            throw new NotFoundException("该订单不存在");
        return orderEntity;
    }

    public Long getSendNum(Integer id, Integer pf){
        System.out.println("我"+id+"是"+pf);
        return deliverDetail.countAllOrderSend(pf,id);
    }

    /**
     * 加载订单
     * @param id
     * @return
     * @throws NotFoundException
     */
    public OrderVo loadBy(Long id) throws NotFoundException {
        OrderVo orderEntity = orderMapper.load(id);
        if (orderEntity == null)
            throw new NotFoundException("该订单/合同不存在");
        orderEntity.setSendGoods(getOrderSendStatus(id));
        return orderEntity;
    }

    /**
     * 通过客户查询订单
     * @param id
     * @return
     */
    public List<OrderVo> loadOrderByus(Long id){
        return orderMapper.findByCus(id.intValue());
    }



    /**
     * 获取订单发货状态
     * @param id
     * @return
     */
    private String getOrderSendStatus(Long id){
        int wpull = outStorageDao.sumOrderPull(id.intValue());
        if (wpull<=0)
            return "";
        boolean out = false,noOut = false,send = false,noSend = false;
        List<OrderDetailEntity> orderDetailEntities = detailDao.findAll(id.intValue());
        for (OrderDetailEntity detailEntity : orderDetailEntities) {
            Long pay = deliverDetail.countAllOrder(detailEntity.getFormatEntity().getPfId(), id.intValue());
            if (pay >0)
                out = true;
            else
                noOut = true;
            if (pay < detailEntity.getOdNumber())
                noOut = true;
            Long sends = deliverDetail.countAllOrderSend(detailEntity.getFormatEntity().getPfId(), id.intValue());
            if (sends >0)
                send = true;
            else
                noSend = true;
            if (sends < detailEntity.getOdNumber())
                noSend = true;
        }
        if (send && !noSend)
            return "已发货";
        if (send && noSend)
            return "部分发货";
        if (out && !noOut)
            return "已出库";
        if (out && noOut)
            return "部分出库";
        return "未出库";

    }

    /**
     * 修改订单
     * @param orderEntity
     * @return
     */
    public boolean modifyOrder(OrderEntity orderEntity,boolean type) throws NotFoundException, ServiceException {
        OrderEntity order =  load(orderEntity.getOrderId().longValue());
        if (order.getOrderStatus() != 0)
            throw new ServiceException("该订单已经结束");
        if (orderEntity.getOrderOk() != 0 && orderEntity.getOrderOk() !=3)
            throw new ServiceException("订单已经锁定");
        modifyData(order,orderEntity);
        try {
            orderDao.save(order);
        }catch (Exception e){
            e.printStackTrace();
            throw new ServiceException("修改订单失败");
        }
        return true;
    }

    /**
     * 修改数据
     * @param entity
     * @param orderEntity
     */
    private void modifyData(OrderEntity entity, OrderEntity orderEntity) throws ServiceException {
        entity.setOrderTitle(orderEntity.getOrderTitle());
        entity.setTbQuoteByQuoteId(orderEntity.getTbQuoteByQuoteId());
        entity.setOrderCategory(orderEntity.getOrderCategory());
        entity.setOrderTotal(orderEntity.getOrderTotal());
        entity.setOrderPayWay(orderEntity.getOrderPayWay());
        entity.setOrderDate(orderEntity.getOrderDate());
        entity.setOrderLatestDate(orderEntity.getOrderLatestDate());
        entity.setContactsEntity(orderEntity.getContactsEntity());
        entity.setTbUserByTbUserId(orderEntity.getTbUserByTbUserId());
        entity.setTbUserByUserId(orderEntity.getTbUserByUserId());
        entity.setOrderNewDate(orderEntity.getOrderNewDate());
        entity.setOrderStatus(orderEntity.getOrderStatus());
        entity.setOrderKnotWay(orderEntity.getOrderKnotWay());
        entity.setProjectEntity(orderEntity.getProjectEntity());
        entity.setOrderOther(orderEntity.getOrderOther());
        entity.setTbAddressByAddressId(orderEntity.getTbAddressByAddressId());
        if (!entity.getTbCustomerByCusId().getCusId().equals(orderEntity.getTbCustomerByCusId().getCusId()))
            throw new ServiceException("不能修改客户");
    }

    /**
     * 高级查询
     * @param search
     * @return
     */
    public PageEntity<OrderVo> findAll(OrderSearch search) {
        if (search == null)
            return new PageEntity<OrderVo>(0L,null);
        String order = search.getPage().getSort(map);
        if (order.length() <=0)
            order = "order_id desc";
        Page<OrderVo> page1 = PageHelper.startPage(search.getPage().getPage(),search.getPage().getSize(),
                order);
        orderMapper.findAll(search);
        System.out.println(page1);
        return new PageEntity<>(page1.getTotal(), page1.getResult());
    }
    /**
     * 高级查询
     * @param search
     * @return
     */
    public PageEntity<OrderDetail> findAll(OrderDetailSearch search) {
        if (search == null)
            return new PageEntity<OrderDetail>(0L,null);
        String order = search.getPage().getSort(map);
        if (order.length() <=0)
            order = "OD_ID desc";
        Page<OrderDetail> page1 = PageHelper.startPage(search.getPage().getPage(),search.getPage().getSize(),
                order);
        orderDetailMapper.findAll(search);
        return new PageEntity<>(page1.getTotal(), page1.getResult());
    }

    /**
     * 添加交付计划
     * @param detailEntity
     * @throws NotFoundException
     * @throws ServiceException
     */
    public void addOneDetail(OrderDetailEntity detailEntity) throws NotFoundException, ServiceException {
        ProductFormatEntity formatEntity = productService.load(detailEntity.getFormatEntity().getPfId());
        detailEntity.setOdPrice(formatEntity.getPfPrice());
        detailEntity.setOdProfit(detailEntity.getOdTotal().subtract(detailEntity.getOdPrice().
                multiply(BigDecimal.valueOf(detailEntity.getOdNumber()))));
        OrderEntity orderEntity = load(detailEntity.getTbOrderByOrderId().getOrderId().longValue());
        if (orderEntity.getOrderOk() != 0 && orderEntity.getOrderOk() !=3)
            throw new ServiceException("合同已锁定");
        if (orderEntity.getOrderType())
            throw new ServiceException("请选择合同");
        try {
            detailDao.save(detailEntity);
        }catch (Exception e){
            e.printStackTrace();
            throw new ServiceException("添加交付计划错误");
        }
    }


    /**
     * 加载订单明细
     * @param id
     * @return
     */
    public List<OrderDetail> loadDeatil(Long id) {
        List<OrderDetailEntity> orderDetailEntities = detailDao.findAll(id.intValue());
        List<OrderDetail> orderDetails = new ArrayList<>();
        for (OrderDetailEntity detailEntity : orderDetailEntities){
            Long pay = deliverDetail.countAllOrder(detailEntity.getFormatEntity().getPfId(),id.intValue());
            OrderDetail orderDetail = new OrderDetail(detailEntity,pay);
            orderDetails.add(orderDetail);
        }
        System.out.println("我是分割线--"+orderDetailEntities);
        return orderDetails;
    }



    /**
     * 通过客户加载交付计划
     * @param id
     * @return
     */
    public List<OrderDetailEntity> loadDetailByCus(Long id){
        return orderDetailMapper.findAllByCus(id);
    }

    /**
     * 批量删除订单
     * @param ids
     * @return
     * @throws NotFoundException
     * @throws ServiceException
     */
    public boolean deleteAll(Long[] ids) throws NotFoundException, ServiceException {
        for (Long id : ids) {
           deleteOrder(id);
        }
        return true;
    }

    /**
     * 修改订单状态
     * @param id
     * @param value
     */
    public void modifyStatus(Long id, Long value) throws NotFoundException, ServiceException {
        OrderEntity orderEntity = load(id);
        orderEntity.setOrderStatus(value.intValue());
        try {
            orderDao.save(orderEntity);
        }catch (Exception e){
            e.printStackTrace();
            throw new ServiceException("修改订单状态失败");
        }
    }

    /**
     * 修改订单明细
     * @param detailEntities
     * @return
     */
    public boolean addDetail(List<OrderDetailEntity> detailEntities, Long id) throws NotFoundException, ServiceException {
        OrderEntity orderEntity = load(id);
        if (orderEntity.getOrderStatus()!=0)
            throw new ServiceException("该订单已经结束");
        if (orderEntity.getOrderOk() != 0 && orderEntity.getOrderOk() !=3)
            throw new ServiceException("订单已锁定");
        List<OrderDetailEntity> dds = buildDetails(detailEntities,orderEntity);
        List<OrderDetailEntity> deleteList = new ArrayList<>();
        getDeleteDetail(orderEntity, dds, deleteList);
        try {
            detailDao.save(dds);
            detailDao.delete(deleteList);
        }catch (Exception e){
            e.printStackTrace();
            throw new ServiceException("修改订单明细失败");
        }
        return true;
    }

    /**
     * 报价单转订单
     * @param id
     */
    public void quoteToOrder(Long id) throws NotFoundException, ServiceException {
        QuoteEntity quoteEntity = quoteService.load(id);
        List<OrderDetailEntity> detailEntities = buildOrderByQuote(quoteEntity);
        quoteEntity.setIsOrder(1L);
        try {
//            quoteService.modify(quoteEntity);
            detailDao.save(detailEntities);
        }catch (Exception e){
            e.printStackTrace();
            throw new ServiceException("添加订单失败");
        }
    }

    /**
     * 报价单转未订单
     * @param quoteEntity
     * @return
     */
    private List<OrderDetailEntity> buildOrderByQuote(QuoteEntity quoteEntity) {
        OrderEntity orderEntity = new OrderEntity(
               quoteEntity.getQuoteTheme(),quoteEntity.getQuoteNumber(), BigDecimal.valueOf(quoteEntity.getTotalQuote()),
                quoteEntity.getQuoteTime(),0,true,quoteEntity.getRemarks(),false,2,quoteEntity.getTbUserByUserId(),
                quoteEntity.getTbCustomerByCusId(),quoteEntity.getTbSaleOppByOppId(),quoteEntity.getTbContactsBy接收人Id()
        );
        List<QuoteDetailEntity> quoteDetailEntities = (List<QuoteDetailEntity>) quoteEntity.getTbQuoteDetailsByQuoteId();
        List<OrderDetailEntity> detailEntities = new ArrayList<>();
        for (QuoteDetailEntity quoteDetailEntity : quoteDetailEntities) {
            OrderDetailEntity orderDetailEntity = new OrderDetailEntity(
                    quoteDetailEntity.getAmount().longValue(),BigDecimal.valueOf(quoteDetailEntity.getUnitPrice()),
                    BigDecimal.valueOf(quoteDetailEntity.getMoney()),quoteDetailEntity.getRemarks(),orderEntity,
                    quoteDetailEntity.getTbProductFormatByPfId(),
                    BigDecimal.valueOf(quoteDetailEntity.getMoney()).subtract(
                            quoteDetailEntity.getTbProductFormatByPfId().getPfCost().multiply(
                                    BigDecimal.valueOf(quoteDetailEntity.getAmount())))
                    ,quoteEntity.getQuoteTime()
            );
            detailEntities.add(orderDetailEntity);
        }
        return detailEntities;
    }

    /**
     * 要删除的订单明细
     * @param orderEntity
     * @param dds
     * @param deleteList
     */
    private void    getDeleteDetail(OrderEntity orderEntity, List<OrderDetailEntity> dds, List<OrderDetailEntity> deleteList) {
        boolean delete;
        if (orderEntity.getTbOrderDetailsByOrderId() != null)
            for (OrderDetailEntity orderDetailEntity : orderEntity.getTbOrderDetailsByOrderId()) {
                delete = true;
                for (OrderDetailEntity dd : dds) {
                    if (orderDetailEntity.getOdId().equals(dd.getOdId())){
                        delete = false;
                        break;
                    }
                }
                if (delete)
                    deleteList.add(orderDetailEntity);
            }
    }

    /**
     * 修改发货数据后修改明细数据
     * @param id
     * @throws NotFoundException
     * @throws ServiceException
     */
    public void rereshDetail(Long id) throws NotFoundException, ServiceException {
        OrderEntity orderEntity = load(id);
        List<OrderDetailEntity> dds = (List<OrderDetailEntity>) orderEntity.getTbOrderDetailsByOrderId();
        try {
            detailDao.save( getSendDetail(orderEntity, (List<DeliverDetailEntity>) orderEntity.getTbDeliverDetailsByOrderId(),dds));
        }catch (Exception e){
            e.printStackTrace();
            throw new ServiceException("刷新订单明细失败");
        }
    }
    /**
     * 建造订单明细（已经交付的产品会自动生成明细
     * @param detailEntities
     * @throws NotFoundException
     */
    private List<OrderDetailEntity> buildDetails(List<OrderDetailEntity> detailEntities, OrderEntity orderEntity)
            throws NotFoundException, ServiceException {
        List<DeliverDetailEntity> deliverDetailEntities = deliverDetail.findAllByOrder(orderEntity.getOrderId());
        List<OrderDetailEntity> orderDetailEntities = (List<OrderDetailEntity>) orderEntity.getTbOrderDetailsByOrderId();
        List<OrderDetailEntity> entities = new ArrayList<>();
        if (detailEntities== null)
            return entities;
        getOldDetail(detailEntities, orderDetailEntities, entities);
        getNewDetail(detailEntities, orderEntity, entities);
        entities.addAll(getSendDetail(orderEntity, deliverDetailEntities, entities));
        return entities;

    }

    /**
     * 获取已经发货但是没有在明细的数据
     * @param orderEntity
     * @param deliverDetailEntities
     * @param entities
     */
    private List<OrderDetailEntity> getSendDetail(OrderEntity orderEntity, List<DeliverDetailEntity> deliverDetailEntities, List<OrderDetailEntity> entities) {
        boolean in;
        List<OrderDetailEntity> sends = new ArrayList<>();
        for (DeliverDetailEntity deliverDetailEntity : deliverDetailEntities) {
            in = false;
            for (OrderDetailEntity entity : entities) {
                if (deliverDetailEntity.getFormatEntity().getPfId().equals(entity.getFormatEntity().getPfId())){
                    in = true;
                    break;
                }
            }
            if (!in){
                OrderDetailEntity o = new OrderDetailEntity(orderEntity,deliverDetailEntity.getFormatEntity());
                sends.add(o);
            }

        }
        return sends;
    }

    /**
     * 添加新的明细数据
     * @param detailEntities
     * @param orderEntity
     * @param entities
     * @throws NotFoundException
     */
    private void getNewDetail(List<OrderDetailEntity> detailEntities, OrderEntity orderEntity, List<OrderDetailEntity> entities) throws NotFoundException {
        for (OrderDetailEntity detailEntity : detailEntities) {
            if (detailEntity.getOdNumber() != 0) {
                ProductFormatEntity productFormatEntity = productService.load(detailEntity.getFormatEntity().getPfId());
                OrderDetailEntity e = new OrderDetailEntity(orderEntity, productFormatEntity);
                e.setOdNumber(detailEntity.getOdNumber());
                e.setOdTotal(detailEntity.getOdTotal());
                e.setOdProfit(
                        e.getOdTotal().subtract(e.getFormatEntity().getPfCost().multiply(
                                BigDecimal.valueOf(e.getOdNumber()))));
                entities.add(e);
            }
        }
    }

    /**
     * 修改明细数据
     * @param detailEntities
     * @param orderDetailEntities
     * @param entities
     */
    private void getOldDetail(List<OrderDetailEntity> detailEntities,
                              List<OrderDetailEntity> orderDetailEntities, List<OrderDetailEntity> entities) {
        for (OrderDetailEntity orderDetailEntity : orderDetailEntities) {
            Iterator<OrderDetailEntity> iterator = detailEntities.iterator();
            while (iterator.hasNext()){
                OrderDetailEntity detailEntity = iterator.next();
                if (orderDetailEntity.getFormatEntity().getPfId().equals(detailEntity.getFormatEntity().getPfId())){
                    orderDetailEntity.setOdNumber(detailEntity.getOdNumber());
                    orderDetailEntity.setOdTotal(detailEntity.getOdTotal());
                    orderDetailEntity.setOdProfit(orderDetailEntity.getOdTotal().subtract(orderDetailEntity.getFormatEntity().getPfCost().multiply(BigDecimal.valueOf(orderDetailEntity.getOdNumber()))));
                    if (orderDetailEntity.getOdNumber() != 0)
                        entities.add(orderDetailEntity);
                    iterator.remove();
                    break;
                }
            }
        }
    }

    public long countByUser(Long userId)throws ServiceException{
        try {
            return orderDao.countAllByTbUserByUserId(userId);
        }catch (Exception e){
            e.printStackTrace();
            throw new ServiceException("统计失败");
        }
    }
    public long countByMonth()throws ServiceException{
        try {
            Calendar calendar = Calendar.getInstance();
            int year = calendar.get(Calendar.YEAR);
            int month = calendar.get(Calendar.MONTH)+1;
            return orderDao.countAllByMonth(year, month);
        }catch (Exception e){
            e.printStackTrace();
            throw new ServiceException("统计失败");
        }
    }
}
